package com.pansoft.xmlparse;

import android.util.Log;

import java.lang.reflect.Method;

/**
 * 用于解析时对组件和模型对象进行属性操作
 *
 * @author zhangjg 2013 12 09
 */
public class PropertyUtils {


    private static final String TAG = "PropertyUtils";


    /*++++++++++++++++++++++++++++   属性类型        ++++++++++++++++++++++++*/

    public static final String TYPE_STRING = "String";
    public static final String TYPE_NUMBER = "Number";
    public static final String TYPE_BOOLEAN = "Boolean";
    public static final String TYPE_INT = "int";
    public static final String TYPE_UINT = "uint";


    /*++++++++++++++++++++++++++++   属性类型        ++++++++++++++++++++++++*/


    /**
     * 为指定的bean设置属性, 要设置的属性值为解析出来的原生字符串, 即<P>标签中的文本节点
     * 在方法内根据attrType指定的属性类型的名字, 可以将原生字符串的值转换成基本数据类型
     *
     * @param bean        要设置属性的bean对象. 如comp.getProperties()
     * @param attrName    属性名 .如 "percentX"
     * @param attrType    属性的类型. 如"Number", "int"
     * @param stringValue 属性值. 如"0.1", 对应<P>标签中的文本节点
     * @throws Exception
     */
    public static void setProperty(Object bean, String attrName, String attrType, String stringValue) throws Exception {


        Class attrClazz = null;    //属性的类型
        Object valueToSet = null;        //属性值

        if (TYPE_STRING.equals(attrType)) {   //属性为String类型

            attrClazz = String.class;
            valueToSet = stringValue;

        } else if (TYPE_NUMBER.equals(attrType)) {

            attrClazz = float.class;
            valueToSet = Float.parseFloat(stringValue);

        } else if (TYPE_BOOLEAN.equals(attrType)) {

            attrClazz = boolean.class;
            valueToSet = Boolean.parseBoolean(stringValue);

        } else if (TYPE_INT.equals(attrType)) {

            attrClazz = int.class;
            valueToSet = Integer.parseInt(stringValue);

        } else if (TYPE_UINT.equals(attrType)) {

            attrClazz = int.class;
            valueToSet = Integer.parseInt(stringValue);

        }

        //todo 经过测试 ReflectUtils 反射效率很低，差两倍。。。
//        ReflectUtils reflectUtils =  ReflectUtils.reflect(bean);
        try {

//            reflectUtils.method(getSetterMethodName(attrName),valueToSet);

            Method setter = bean.getClass().getMethod(getSetterMethodName(attrName), attrClazz);
            //	Log.i(TAG, "组件中已添加该属性"+getSetterMethodName(attrName));
            setter.invoke(bean, valueToSet);

        } catch (Exception e) {
            //属性放入map
//            Method setter = bean.getClass().getMethod(getSetterMethodName(attrName), attrClazz);
            try {
                Method putFieldMethod = bean.getClass().getMethod("putField", String.class,String.class);
                putFieldMethod.invoke(bean, attrName, stringValue);

//                reflectUtils.method("putField",attrName,stringValue);

            } catch (Exception e1) {
                Log.d(TAG, "组件中还未添加该属性" + attrName);
            }


        }


    }


    /**
     * 为指定的bean对象设置属性, 要设置的属性值是除了String之外的其他引用数据类型
     * attrClassName必须是被映射之后的java类型的全限定名
     *
     * @param bean          要设置属性的bean对象. 如comp.getProperties()
     * @param attrName      属性名 .如 "percentX"
     * @param attrClassName 属性的类型. 如"java.lang.Float"
     * @param value         属性值. 一般为被引用的对象
     * @throws Exception
     */
    public static void setProperty(Object bean, String attrName, String attrClassName, Object value) throws Exception {

        //根据属性的类型名称获取属性类型的Class对象
        Class attrClazz = Class.forName(attrClassName);

        //得到setter方法
        try {
            Method setter = bean.getClass().getMethod(getSetterMethodName(attrName), attrClazz);

            //调用setter方法设置属性
            setter.invoke(bean, value);
        } catch (Exception e) {
            try {
                Method putFieldMethod = bean.getClass().getMethod("putField", attrClazz);
                putFieldMethod.invoke(bean, attrName, value);
            } catch (Exception e1) {
//                e1.printStackTrace();
            }
//            Log.d(TAG, "组件中还未添加该方法");
        }
    }

    /**
     * 根据属性的名称获得setter方法名
     *
     * @param AttributeName
     * @return
     */
    private static String getSetterMethodName(String AttributeName) {

        return "set" + firstUpperCase(AttributeName);

    }

    /**
     * 将字符串的第一个字符转成大写
     *
     * @param toUpper
     * @return
     */
    private static String firstUpperCase(String toUpper) {

        String first = toUpper.substring(0, 1);
        String upperFirst = first.toUpperCase();

        return upperFirst + toUpper.substring(1);
    }

}
